package simpledb.execution;

import simpledb.common.DbException;
import simpledb.storage.Field;
import simpledb.storage.Tuple;
import simpledb.storage.TupleDesc;
import simpledb.transaction.TransactionAbortedException;

import java.util.*;

/**
 * OrderBy 是一个执行算子，用于实现关系代数中的排序操作（ORDER BY）。
 * 它从子算子中读取所有元组，按指定字段进行排序，并逐个返回有序的元组。
 */
public class OrderBy extends Operator {

    private static final long serialVersionUID = 1L;

    // 子算子，提供原始数据
    private OpIterator        child;

    // 输出元组的结构描述（与子算子一致）
    private final TupleDesc   td;

    // 存储从子算子中读取的所有元组
    private final List<Tuple> childTups        = new ArrayList<>();

    // 按照哪个字段排序
    private final int         orderByField;

    // 排序字段的名称
    private final String      orderByFieldName;

    // 当前遍历器，用于按顺序返回排序后的元组
    private Iterator<Tuple>   it;

    // 是否为升序排序（true 表示升序）
    private final boolean     asc;

    /**
     * 构造一个新的 OrderBy 算子
     *
     * @param orderbyField 要排序的字段索引
     * @param asc 是否为升序排序
     * @param child 子算子，提供待排序的元组
     */
    public OrderBy(int orderbyField, boolean asc, OpIterator child) {
        this.child = child;
        td = child.getTupleDesc();
        this.orderByField = orderbyField;
        this.orderByFieldName = td.getFieldName(orderbyField);
        this.asc = asc;
    }

    /**
     * 获取当前是否为升序排序
     */
    public boolean isASC() {
        return this.asc;
    }

    /**
     * 获取排序字段的索引
     */
    public int getOrderByField() {
        return this.orderByField;
    }

    /**
     * 获取排序字段的名称
     */
    public String getOrderFieldName() {
        return this.orderByFieldName;
    }

    /**
     * 获取输出元组的结构描述（与输入一致）
     */
    public TupleDesc getTupleDesc() {
        return td;
    }

    /**
     * 打开该算子及其子算子，并加载所有元组到内存中进行排序
     */
    public void open() throws DbException, NoSuchElementException, TransactionAbortedException {
        child.open();

        // 从子算子中读取所有元组并存储到列表中
        while (child.hasNext())
            childTups.add(child.next());

        // 使用自定义比较器对元组进行排序
        childTups.sort(new TupleComparator(orderByField, asc));

        // 创建迭代器以便后续逐条返回
        it = childTups.iterator();

        super.open();
    }

    /**
     * 关闭该算子及其子算子，释放资源
     */
    public void close() {
        super.close();
        it = null; // 清空迭代器
    }

    /**
     * 重置迭代器，使得可以重新遍历排序后的结果
     */
    public void rewind() {
        it = childTups.iterator(); // 重新创建迭代器
    }

    /**
     * fetchNext 的具体实现。返回排序后的下一个元组。
     *
     * @return 下一个排序后的元组；若无更多元组则返回 null
     */
    protected Tuple fetchNext() throws NoSuchElementException {
        if (it != null && it.hasNext()) {
            return it.next();
        } else {
            return null;
        }
    }

    /**
     * 获取当前算子的子算子数组
     */
    @Override
    public OpIterator[] getChildren() {
        return new OpIterator[] { this.child };
    }

    /**
     * 设置当前算子的子算子
     */
    @Override
    public void setChildren(OpIterator[] children) {
        this.child = children[0];
    }

}

/**
 * TupleComparator 是一个内部类，用于比较两个元组在指定字段上的大小关系，
 * 支持升序或降序排序。
 */
class TupleComparator implements Comparator<Tuple> {

    // 要比较的字段索引
    final int     field;

    // 是否为升序排序
    final boolean asc;

    /**
     * 构造一个新的 TupleComparator 实例
     *
     * @param field 要比较的字段索引
     * @param asc 是否为升序排序
     */
    public TupleComparator(int field, boolean asc) {
        this.field = field;
        this.asc = asc;
    }

    /**
     * 比较两个元组在指定字段上的大小关系
     *
     * @param o1 第一个元组
     * @param o2 第二个元组
     * @return 比较结果：负值、零或正值表示小于、等于或大于
     */
    public int compare(Tuple o1, Tuple o2) {
        Field t1 = o1.getField(field);
        Field t2 = o2.getField(field);

        if (t1.compare(Predicate.Op.EQUALS, t2))
            return 0;

        if (t1.compare(Predicate.Op.GREATER_THAN, t2))
            return asc ? 1 : -1;
        else
            return asc ? -1 : 1;
    }
}
